import re
from django import http
from django.contrib.auth import login
from django.http import JsonResponse
from django.shortcuts import render, redirect
from django.urls import reverse
from django_redis import get_redis_connection

from apps.oauth.models import OAuthQQUser
from apps.oauth.utils import generic_openid_token, check_openid_tocken
from apps.users.models import User
from meiduo import settings
#https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=101518219&redirect_uri=http://www.meiduo.site:8000/oauth_callback&state=lalalala

#http://路由/?key=value&key1=value1
# 由是 以? 为分割
# ?前边为请求的路由
# ?后边为请求的参数
from django.views import View

from utils.response_code import RETCODE
from QQLoginTool.QQtool import OAuthQQ
import logging

loger = logging.Logger('django')


#qq跳转url
class OauthQQURLView(View):
    def get(self,request):

        # 提供appid和redirect-uri
        # 反馈一个跳转的url
        # 1.创建OAuthQQ
        state = request.GET.get('next')
        qq=OAuthQQ(
            client_id=settings.QQ_CLIENT_ID,
            redirect_uri=settings.QQ_REDIRECT_URI,
            client_secret=settings.QQ_CLIENT_SECRET,
            state=state

            )
        # 2.调用实例方法
        login_url = qq.get_qq_url()

        # login_url = 'https://graph.qq.com/oauth2.0/show?which=Login&display=pc&response_type=code&client_id=101518219&redirect_uri=http://www.meiduo.site:8000/oauth_callback&state=test'
        return JsonResponse ({'code':RETCODE.OK,'errmsg':'ok','login_url':login_url})




class OauthQQUserView(View):
    def get(self,request):
        # 1.
        # 获取code(是用户同意登陆之后, qq服务器返回给我们的)
        # 2.
        # 通过code换取token(我们需要把code以及我们创建应用的serect
        # 一并给qq服务器, qq服务器会认证
        # 认证没有问题会返回给我们token)
        # 3.
        # 根据token换取openid(qq文档要求我们建立
        # openid和当前应用user的一对一关系)
        # 4.
        # 判断openid所对应的user信息是否存在
        # 5.
        # 如果不存在则进行绑定
        # 6.
        # 如果存在则进行登陆跳转
        # 1.获取code
        code = request.GET.get('code')
        if code is None:

            return http.HttpResponseBadRequest('参数有错误')
        # 2.通过code换取token
        # 2.1创建QQ实例
        qq = OAuthQQ(
            client_id=settings.QQ_CLIENT_ID,
            redirect_uri=settings.QQ_REDIRECT_URI,
            client_secret=settings.QQ_CLIENT_SECRET,
        )
        # 通过code换取token
        token = qq.get_access_token(code)
        # 通过token换取openid
        openid = qq.get_open_id(token)
        # 判断openid所对应的user信息是否存在
        try:
            qquser =OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:

            # 需要对openid加密处理
            openid_token = generic_openid_token(openid)


        # 如果不存在则进行绑定
        #     返回openid
            return render(request,'oauth_callback.html',context={'access_token':openid_token})
        else:

            # 如果存在则进行登陆跳转
            user = qquser.user
            # 保持登陆状态
            login(request,user)

            next = request.GET.get('state')
            if next:
                response =redirect(next)
            else:
            # 设置cokies

                response = redirect(reverse('contents:index'))

            response.set_cookie('username',user.username,max_age=14*24*3600)
            return response


        # return  render(request,'oauth_callback.html



    def post(self,request):
        """
          需求:
         当用户点击保存的时候,需要让前端将 openid_token,mobile,password,sms_code 提交给后端

         后端:

         大体步骤:
         1.接收数据
         2.验证数据
            手机号
            密码
            短信验证码
            openid_token
        3.绑定信息
            openid      是通过对oepnid_token的解密来获取
            user        需要根据 手机号进行判断
                            如果手机号注册,已经有user信息
                            如果没有注册,我们就创建一个user用户
        4.登陆状态保持
        5.cookie
        6.返回相应


        """

        # 1.接收数据
        data = request.POST
        mobile = data.get('mobile')
        password = data.get('password')
        sms_code_client = data.get('sms_code')
        access_token = data.get('access_token')

        # 2.验证数据
        if not all([mobile,password,mobile,sms_code_client,access_token]):

            return http.HttpResponseBadRequest('参数不全')

        # if not re.match(r'^[0-9a-zA-Z_-]{5,20}$',username):
        #
        #     return http.HttpResponseBadRequest('用户名不满足条件')
        if not re.match(r'^1[3-9]\d{9}$',mobile):
            return http.HttpResponseBadRequest('手机号不满足条件')

        if not re.match(r'^[0-9A-Za-z]{8,20}$',password):
            return http.HttpResponseBadRequest('密码格式不正确')

        # 手机号
        # 密码
        # 短信验证码
        redis_conn = get_redis_connection('code')

        # 获取redis中的短信验证码
        sms_code_server = redis_conn.get('sms_%s' % mobile)

        # 判断redis是否过期
        if not sms_code_server:
            return http.HttpResponseBadRequest('短信验证码过期')
        # 比对
        if sms_code_server.decode() != sms_code_client:
            return http.HttpResponseForbidden('短信验证码不一致')
        # openid_token

        # 3.绑定信息

        openid = check_openid_tocken(access_token)
        if openid is None:
            return http.HttpResponseBadRequest('openid错误')
            # openid          是通过对oepnid_token的解密来获取
            # user        需要根据        手机号进行判断
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist :

            user = User.objects.create_user(
                username=mobile,
                password=password,
                mobile=mobile
            )
        else:
            if not user.check_password(password):
                return http.HttpResponseBadRequest('密码错误')
        try:
            OAuthQQUser.objects.create(
                openid=openid,
                user = user
            )
        except Exception as e:
            loger.error(e)

            return http.HttpResponseBadRequest('数据库错误')


        #             如果手机号注册, 已经有user信息
        #             如果没有注册, 我们就创建一个user用户
        # 4.登陆状态保持
        login(request,user)
        # 5.cookie
        response = redirect(reverse('contents:index'))
        response.set_cookie('user',user.username,max_age=14*24*3600)
        # 6.返回相应
        return response


"""
############################itsdangerous加密#####################################
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from meiduo import settings
# 1.创建实例对象
#secret_key, expires_in
#secret_key         密钥      习惯上:使用setting中的SECRET_KEY
# expires_in        过期时间(单位:秒)
s = Serializer(settings.SECRET_KEY,300)


# 2.组织数据
data = {'openid':'abcde'}

# 3.加密处理
token = s.dumps(data)
# b'eyJpYXQiOjE1NTgwMjAxNTksImFsZyI6IkhTNTEyIiwiZXhwIjoxNTU4MDIwNDU5fQ.eyJvcGVuaWQiOiJhYmNkZSJ9.Z-V1Gy9RlTYI328i3bjYSOwNOqhhbYPm5oNIpz7Ma8lX6HaGG--TkOA_3t016QnFIKGhIULt1G3UeoPJ_7sltw'
token.decode()


############################itsdangerous解密#####################################
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from meiduo import settings
# 1.创建实例对象

s = Serializer(settings.SECRET_KEY,300)

# 2.对数据解密

s.loads(token)



###############################itsdangerous 解密失败（过期)#####################################################
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from meiduo import settings
# 1.创建实例对象
#secret_key, expires_in
#secret_key         密钥      习惯上:使用setting中的SECRET_KEY
# expires_in        过期时间(单位:秒)
s = Serializer(settings.SECRET_KEY,1)


# 2.组织数据
data = {'openid':'abcde'}

# 3.加密处理
token = s.dumps(data)
# b'eyJpYXQiOjE1NTgwMjAxNTk

###############################itsdangerous 解密失败（过期)#####################################################
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from meiduo import settings
# 1.创建实例对象
#secret_key, expires_in
#secret_key         密钥      习惯上:使用setting中的SECRET_KEY
# expires_in        过期时间(单位:秒)
s = Serializer(settings.SECRET_KEY,1)


# 2.组织数据
data = {'openid':'abcde'}

# 3.加密处理
token1 = s.dumps(data)

token1.decode()

#报错Traceback (most recent call last):
#   File "<console>", line 1, in <module>
#   File "/home/python/.virtualenvs/py3_meiduo/lib/python3.5/site-packages/itsdangerous/jws.py", line 205, in loads
#     date_signed=self.get_issue_date(header),
# itsdangerous.exc.SignatureExpired: Signature expired

###############################itsdangerous 解密失败（篡改token数据)#####################################################
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from meiduo import settings
# 1.创建实例对象
#secret_key, expires_in
#secret_key         密钥      习惯上:使用setting中的SECRET_KEY
# expires_in        过期时间(单位:秒)
s = Serializer(settings.SECRET_KEY,300)


# 2.组织数据
data = {'openid':'abcde'}

# 3.加密处理
token2 = s.dumps(data)

token2.decode()
#'eyJpYXQiOjE1NTgwNzc3OTcsImV4cCI6MTU1ODA3ODA5NywiYWxnIjoiSFM1MTIifQ.eyJvcGVuaWQiOiJhYmNkZSJ9.jOx8h2XzPOCJ4Bb0X2RoyXc4Hcub2AGm0dGdHAbrCfbZtkin-2anyn0o51pO9yaRkBkDzkVI4B9n-bdtWqgjUg'

# 解密失败提示Traceback (most recent call last):
#   File "<console>", line 1, in <module>
#   File "/home/python/.virtualenvs/py3_meiduo/lib/python3.5/site-packages/itsdangerous/jws.py", line 187, in loads
#     self, s, salt, return_header=True
#   File "/home/python/.virtualenvs/py3_meiduo/lib/python3.5/site-packages/itsdangerous/jws.py", line 143, in loads
#     self.make_signer(salt, self.algorithm).unsign(want_bytes(s)),
#   File "/home/python/.virtualenvs/py3_meiduo/lib/python3.5/site-packages/itsdangerous/signer.py", line 169, in unsign
#     raise BadSignature("Signature %r does not match" % sig, payload=value)
# itsdangerous.exc.BadSignature: Signature b'jOx8h2XzPOCJ4Bb0X2RoyXc4Hcub2AGm0dGdHAbrCfbZtkin-2anyn0o51pO9yaRkBkDzkVI4B9n-bdtWqUg' does not match

"""

